package cn.jbolt.core.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类
 *
 * @author Michael
 *
 */
public class JBoltStringUtil {
	public static final String EMPTY = "";
	private static final String PATTERN_NUMBER_STR = "\\d+";
	private static final String PATTERN_REMOVE_NUMBER_STR = "\\D+";
	private static final Pattern PATTERN_NUMBER = Pattern.compile(PATTERN_NUMBER_STR);
	private static final Pattern PATTERN_REMOVE_NUMBER = Pattern.compile(PATTERN_REMOVE_NUMBER_STR);
	private static final Pattern imgPattern = Pattern.compile("(?<=\\<img)[^>]*src=\"([^\"]+)");

	/**
	 * 从html代码中提取第一个图片地址
	 * @param html
	 * @return
	 */
	public static String getImgUrlFromHtml(String html) {
		if (isBlank(html)) return null;
		Matcher matcher = imgPattern.matcher(html);
		if (matcher.find() && matcher.groupCount() == 1) {
			return matcher.group(1);
		}
		return null;
	}
	/**
	 * 截取数字 Integer类型
	 * @param content
	 * @return
	 */
	public static Integer splitInt(String content) {
		Matcher matcher = PATTERN_NUMBER.matcher(content);
		while (matcher.find()) {
			return Integer.parseInt(matcher.group(0));
		}
		return null;
	}
	/**
	 * 截取数字 返回string
	 * @param content
	 * @return
	 */
	public static String getNumber(String content) {
		Matcher matcher = PATTERN_NUMBER.matcher(content);
		while (matcher.find()) {
			return matcher.group(0);
		}
		return null;
	}

	/**
	 * 删除非中文字符
	 * @param str
	 * @return
	 */
	public static String removeNonChinese(String str) {
		String regex = "[^\\u4e00-\\u9fa5]";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		return matcher.replaceAll("");
	}
	/**
	 * 截取非数字
	 * @param content
	 * @return
	 */
	public static String removeNumber(String content) {
		Matcher matcher = PATTERN_REMOVE_NUMBER.matcher(content);
		while (matcher.find()) {
			return matcher.group(0);
		}
		return null;
	}


	public static String unescapeJava(String str) throws IOException {
		Writer out = new StringWriter();
		if (str != null) {
			int sz = str.length();
			StringBuilder unicode = new StringBuilder(4);
			boolean hadSlash = false;
			boolean inUnicode = false;

			for (int i = 0; i < sz; ++i) {
				char ch = str.charAt(i);
				if (inUnicode) {
					unicode.append(ch);
					if (unicode.length() == 4) {
						try {
							int nfe = Integer.parseInt(unicode.toString(), 16);
							out.write((char) nfe);
							unicode.setLength(0);
							inUnicode = false;
							hadSlash = false;
						} catch (NumberFormatException var9) {
						}
					}
				} else if (hadSlash) {
					hadSlash = false;
					switch (ch) {
					case '\"':
						out.write(34);
						break;
					case '\'':
						out.write(39);
						break;
					case '\\':
						out.write(92);
						break;
					case 'b':
						out.write(8);
						break;
					case 'f':
						out.write(12);
						break;
					case 'n':
						out.write(10);
						break;
					case 'r':
						out.write(13);
						break;
					case 't':
						out.write(9);
						break;
					case 'u':
						inUnicode = true;
						break;
					default:
						out.write(ch);
					}
				} else if (ch == 92) {
					hadSlash = true;
				} else {
					out.write(ch);
				}
			}

			if (hadSlash) {
				out.write(92);
			}

		}
		return out.toString();
	}

	/**
	 * 首字母小写
	 *
	 * @param s
	 * @return
	 */
	public static String toLowerCaseFirstWord(String s) {
		if (isBlank(s)) {
			return s;
		}
		if (Character.isLowerCase(s.charAt(0))) {
			return s;
		}
		if (s.length() == 1) {
			return Character.toLowerCase(s.charAt(0)) + "";
		}
		return Character.toLowerCase(s.charAt(0)) + s.substring(1);
	}

	/**
	 * 首字母大写
	 *
	 * @param s
	 * @return
	 */
	public static String toUpperCaseFirstWord(String s) {
		if (isBlank(s)) {
			return s;
		}
		if (Character.isUpperCase(s.charAt(0))) {
			return s;
		}
		if (s.length() == 1) {
			return Character.toUpperCase(s.charAt(0)) + "";
		}
		return Character.toUpperCase(s.charAt(0)) + s.substring(1);
	}

	public static String toUpperCase(String str) {
		if (isNotBlank(str)) {
			return str.toUpperCase();
		}
		return str;
	}

	/**
	 * 判断空
	 *
	 * @param s
	 * @return
	 */
	public static boolean isBlank(String s) {
		if (s == null || s.trim().equals("")) {
			return true;
		}
		return false;
	}

	/**
	 * 判断不是空
	 *
	 * @param s
	 * @return
	 */
	public static boolean isNotBlank(String s) {
		return !isBlank(s);
	}

	/**
	 * 判断空
	 *
	 * @param s
	 * @return
	 */
	public static boolean isEmpty(String s) {
		if (s == null || s.equals("")) {
			return true;
		}
		return false;
	}

	/**
	 * 判断不是空
	 *
	 * @param s
	 * @return
	 */
	public static boolean isNotEmpty(String s) {
		return !isEmpty(s);
	}

	/**
	 * 判断存在多少个指定字符
	 *
	 * @param s
	 * @param c
	 * @return
	 */
	public static int count(String s, char c) {
		if (s == null) {
			return 0;
		}
		int count = 0;
		for (int i = 0; i < s.length(); i++) {
			if (c == s.charAt(i)) {
				count++;
			}
		}
		return count;
	}

	/**
	 * 数组转字符串
	 *
	 * @param arrays
	 * @return
	 */
	public static String toString(String[] arrays) {
		if (arrays == null) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		for (String array : arrays) {
			sb.append(array);
			sb.append(",");
		}
		sb.deleteCharAt(sb.length() - 1);
		return sb.toString();
	}

	/**
	 * 替换
	 *
	 * @param str
	 * @param from
	 * @param to
	 * @return
	 */
	public static String replace(String str, String from, String to) {
		if (str == null) {
			return null;
		}
		return str.replaceAll(from, to);
	}

	/**
	 * list转字符串
	 *
	 * @param list
	 * @param separator
	 * @return
	 */
	public static String listToString(List<?> list, String separator) {
		if (list == null || list.isEmpty()) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for (Object o : list) {
			if (o == null) {
				continue;
			}
			sb.append(o).append(separator);
		}
		return sb.toString().substring(0, sb.toString().length() - 1);
	}

	/**
	 * array转字符串
	 *
	 * @param args
	 * @param separator
	 * @return
	 */
	public static String arrayToString(String[] args, String separator) {
		if (args == null || args.length == 0) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for (String arg : args) {
			if (arg == null) {
				continue;
			}
			sb.append(arg).append(separator);
		}
		return sb.toString().substring(0, sb.toString().length() - 1);
	}

	/**
	 * 获得字符串的前多少字
	 *
	 * @return
	 */
	public static String getPreWords(String str, int count, String omittedWords) {
		String newStr;
		if (str == null) {
			return null;
		}
		if (str.length() <= count) {
			return str;
		}
		newStr = str.substring(0, count);
		if (omittedWords != null) {
			return newStr + omittedWords;
		}
		return newStr;
	}

	public static String filterEmoji(String source) {
		if (source != null && source.length() > 0) {
			return source.replaceAll("[\ud800\udc00-\udbff\udfff\ud800-\udfff]", "");
		} else {
			return source;
		}
	}

	/**
	 * 判断是否为TextNode
	 *
	 * @param tag
	 * @return
	 */
	public static boolean isTextNode(String tag) {
		return "#text".equalsIgnoreCase(tag);
	}

	public static boolean isHr(String tag) {
		return "hr".equalsIgnoreCase(tag);
	}

	public static boolean isPbr(Node element) {
		String html = element.outerHtml();
		return "<p><br></p>".equalsIgnoreCase(html)
				||
				"<p><br/></p>".equalsIgnoreCase(html)
				||
				(element.childNodeSize() == 1 && "br".equalsIgnoreCase(element.childNodes().get(0).nodeName()))
				;
	}

	public static boolean isBr(String tag) {
		return "br".equalsIgnoreCase(tag);
	}
	public static boolean isVideo(String tag) {
		return "video".equalsIgnoreCase(tag);
	}

	public static boolean isAudio(String tag) {
		return "audio".equalsIgnoreCase(tag);
	}

	public static boolean isEmbed(String tag) {
		return "embed".equalsIgnoreCase(tag);
	}

	public static boolean isFigure(String tag) {
		return "figure".equalsIgnoreCase(tag);
	}
	public static boolean isImg(String tag) {
		return "img".equalsIgnoreCase(tag);
	}
	public static boolean isNotNullSpan(Node node) {
		return !(node.hasAttr("class") && node.attr("class").equals("null"));
	}

	/**
	 * 判断是否为script tag标签节点
	 *
	 * @param tag
	 * @return
	 */
	public static boolean isScriptNode(String tag) {
		return "script".equalsIgnoreCase(tag);
	}

	/**
	 * 判断是否为DateNode
	 *
	 * @param tag
	 * @return
	 */
	public static boolean isDataNode(String tag) {
		return "#data".equalsIgnoreCase(tag);
	}

	public static boolean isCommentNode(String tag) {
		return "#comment".equalsIgnoreCase(tag);
	}
	/**
	 * 处理HTML文本的摘要内容
	 * @param htmlContent   html
	 * @param maxLineCount  最大多少行
	 * @param maxWordCount  最多取多少字符
	 * @param maxWordCountWithLFRT   最多取多少字符
	 */
	public static String processHtmlToTextContent(String htmlContent,int maxLineCount,int maxWordCount,int maxWordCountWithLFRT,String[] removeNodeCssSelectors) {
		if(htmlContent == null || htmlContent.length() == 0){
			return null;
		}
		Document doc = Jsoup.parseBodyFragment(htmlContent);
		//进行指定节点的移除
		if(removeNodeCssSelectors!=null && removeNodeCssSelectors.length>0){
			for(String selector:removeNodeCssSelectors){
				Elements needRemoveNodes = doc.select(selector);
				if(needRemoveNodes!=null && needRemoveNodes.size()>0){
					needRemoveNodes.remove();
				}
			}
		}
		List<String> ps = new ArrayList<>();
		List<Node> nodes = doc.body().childNodes();
		//如果获取的Node为空 直接返回Null不处理
		if (nodes.isEmpty()) {
			return null;
		}
		int size = nodes.size();
		if(size == 0){
			return null;
		}
		if(size == 1){
			List<Node> sons = nodes.get(0).childNodes();
			if(sons!=null && sons.size()>1){
				nodes = sons;
				size = nodes.size();
			}
		}
		int totalCount = 0;
		String text;
		Node element;
		String tag;
		for(int i=0;i<size;i++){
			//超过6段
			if(ps.size()>=maxLineCount){
				break;
			}
			//超过200字
			if(totalCount>=maxWordCount){
				break;
			}
			element = nodes.get(i);
			tag = element.nodeName();
			if (isDataNode(tag) ||isScriptNode(tag) || isCommentNode(tag) || isPbr(element)||isHr(tag)||isBr(tag)||isVideo(tag)||isAudio(tag)||isFigure(tag)||isEmbed(tag)||isImg(tag)) {
				text = "";
			}else {
				if (element.outerHtml() != null) {
					text = HtmlUtil.cleanHtmlTag(element.outerHtml());
				} else {
					text = "";
				}
			}
			int textLength = text.trim().length();
			if(textLength>0){
				if(totalCount + textLength>maxWordCount){
					textLength = maxWordCount - totalCount;
					text = StrUtil.subWithLength(text,0,textLength);
				}
				ps.add(text);
				totalCount = totalCount + textLength;
				//超过200字
				if(totalCount>maxWordCount){
					break;
				}
				//超过6段
				if(ps.size()==maxLineCount){
					break;
				}

			}

		}
		String ret = StrUtil.join("\r\n",ps);
		if(ret.length()>maxWordCountWithLFRT){
			return StrUtil.subWithLength(ret,0,maxWordCountWithLFRT);
		}
		return ret;
	}

}
